/* crccitt.c */

/*
 * Taken from http://www.monitor-computing.co.uk/projects/crc16/index.htm
 *

;---------------------------------------------------------------------------------------------
; Hard wired for ^16+^12+^5+1, "CCITT CRC16" - HDLC, X.25
; expects	--	es:edi=pointer to data
;				ecx=data length
; on return	--	ax=CRC16 
;---------------------------------------------------------------------------------------------
loc_crccitt:
		push    dx
		xor		ax,ax
@@:
		xor     al,byte ptr es:[edi]
		inc		edi
		xchg    al,ah
		xor     dx,dx
		mov     dh,ah
		shl     dx,4
		xor     ax,dx
		xor     dx,dx
		mov     dl,ah
		shr     dx,4
		xor     ax,dx
		xor     dx,dx
		mov     dh,ah
		shr     dx,5
		xor     ax,dx
		dec		ecx
		jnz		@B
		pop     dx
		retn
 */

#include <stdio.h>
#include <stdlib.h>

/* Hard wired for ^16+^12+^5+1, "CCITT CRC16" - HDLC, X.25 */

unsigned int add2CRCCITT(unsigned char newData, unsigned short oldCRC)
{
    oldCRC ^= newData;
    oldCRC  = (oldCRC >> 8) | (oldCRC << 8);
    oldCRC ^= (oldCRC & 0xFF00) << 4;
    oldCRC ^= oldCRC >> 12;
    /* It might be better to use '(oldCRC >> 8) >> 4' above as some
       compilers will optimise the shift by eight to a byte operation. */
    oldCRC ^= (oldCRC & 0xFF00) >> 5;
    return oldCRC;
}



int main(int argc, char *argv[])
{
	FILE *in;
	unsigned short crcval = 0;
	int ch;

	if (argc != 2) {
		fprintf(stderr, "Usage: CRCCITT <filename>\n");
		return (1);
	}

	in = fopen(argv[1], "rb");
	if (!in) {
		fprintf(stderr, "couldn't open %s\n", argv[1]);
		return (2);
	}

	while ((ch = fgetc(in)) != EOF)
		crcval = add2CRCCITT((unsigned char)(ch), crcval);

	fclose(in);

	fprintf(stdout, "0x%04X (%u)\n", crcval, crcval);

	return (0);
}

/* end */
